# -*- coding: utf-8 -*-
# @Time    : 2018/8/19 21:53
# @Author  : 周立超！！
# @FileName: utils.py
import functools
import hashlib
import json
import os
import uuid
from contextlib import contextmanager
from datetime import datetime, timedelta
import dateutil.relativedelta
import random
import string

import chardet
import requests
from flask import current_app, request

from libs.error_code import NotFound, Error, UploadFileError, ParmesError

basedir = os.path.abspath(os.getcwd())


def my_avg(*args):
    return round(sum(args) / len(args), 1)


def string_toDate(string):
    return datetime.strptime(string, "%Y-%m-%d").date()


def format_datetime(_datetime):
    if _datetime:
        return _datetime.strftime('%Y-%m-%d %H:%M:%S')
    return ""


def get_date(start_date, time_interval):
    """

    :param date:                    间隔的时间 整型  前几天 为负数 100 后几天为正数 -100
    :param time_interval:           字符类型时间 年月日   ‘20200101’
    :return:                        字符类型时间 年月日   ‘20200101’
    """
    # start_date = datetime.strptime(date, '%Y%m%d')
    now_date = timedelta(days=time_interval)
    a = start_date + now_date
    print(a)
    return a


def isVaildDate2(date):
    try:
        if ":" in date:
            datetime.strptime(date, '%Y-%m-%d %H:%M:%S')
        else:
            datetime.strptime(date, "%Y-%m-%d")
        return 1
    except:
        return 0


def check_item_in_list(check_item, list, type=None):
    if type:
        try:
            check_item = type(check_item)
        except ValueError:
            raise ParmesError()
        except TypeError:
            raise ParmesError()
    if check_item not in list:
        raise ParmesError()


def check_item_in_type(check_item, type=int):
    try:
        check_item = type(check_item)
    except ValueError as e:
        raise ParmesError(message=f'参数异常 {check_item}')
    except TypeError as e:
        raise ParmesError(message='数据类型异常')


def timestamp_toDate(_timestamp):
    if len(_timestamp) == 13:
        return datetime.fromtimestamp(int(_timestamp) / 1000)
    return datetime.fromtimestamp(int(_timestamp))


def day_end(_datetime):
    return datetime.strptime(_datetime.strftime("%Y-%m-%d 23:59:59"), '%Y-%m-%d %H:%M:%S')


def json_has_key(json_post, list):
    if not json_post:
        raise ParmesError()
    for _item in list:
        if json_post.get(_item, None) is None:
            raise ParmesError(message="参数不完整 %s" % _item)


def file_save(_path, _file):
    if not os.path.exists(_path):
        os.makedirs(_path)

    _, ext = os.path.splitext(_file.filename)
    filename = str(datetime.now().strftime('(%Y-%m-%d)')) + str(uuid.uuid1()) + ext

    file_path = os.path.join(_path, filename)
    _file.save(file_path)

    if os.path.exists(file_path):
        return filename
    return ""


def file_save_zip(_path, _file):
    if not os.path.exists(_path):
        os.makedirs(_path)

    _, ext = os.path.splitext(_file.filename)
    # filename = str(datetime.now().strftime('(%Y-%m-%d)')) + str(uuid.uuid1()) + ext
    filename = "test_result.zip"
    file_path = os.path.join(_path, filename)
    _file.save(file_path)

    if os.path.exists(file_path):
        return filename
    return ""


def file_save_to_local(_path, _file):
    if not os.path.exists(_path):
        os.makedirs(_path)

    _, ext = os.path.splitext(_file.filename)
    # filename = str(datetime.now().strftime('(%Y-%m-%d)')) + str(uuid.uuid1()) + ext
    filename = "solution" + ext
    file_path = os.path.join(_path, filename)
    _file.save(file_path)

    if os.path.exists(file_path):
        return filename
    return ""


def get_encoding(_path):
    data = open(_path, "rb").read()
    return chardet.detect(data).get("encoding")


def get_answer_from_result_item(result_item, header_item, key):
    if key in header_item:
        return result_item[header_item.index(key)]
    return ""


def getSign(userkey, adict):
    keys = list(adict.keys())
    keys.sort()
    stringA = ""
    for key in keys:
        if key != 'sign' and adict[key] != "":
            stringA += key + "=" + str(adict[key]) + "&"

    stringA += "key=" + userkey
    # print("string:{}".format(stringA))
    sign = hashlib.md5(stringA.encode(encoding='UTF-8')).hexdigest().lower()
    return sign


def check_sign(userkey, adict):
    sign = getSign(userkey, adict)
    # print("sign:{}".format(sign))
    check_sign = adict.get('sign', None)
    if check_sign is None:
        raise NotFound()
    if sign == check_sign:
        return True
    return False


def verify_sign(func):
    @functools.wraps(func)
    def check(*args, **kwargs):
        current_app.logger.info(
            '{method} {path} : {json}'.format(method=request.method, path=request.environ['PATH_INFO'],
                                              json=request.json))
        if not check_sign(current_app.config.get('MTY_KEY'), request.json):
            raise Error(message=u'签名异常')
        return func(*args, **kwargs)

    return check


def add_to_log(func):
    @functools.wraps(func)
    def check(*args, **kwargs):
        current_app.logger.info(
            '{method} {path} : {json}'.format(method=request.method, path=request.environ['PATH_INFO'],
                                              json=request.json if request.method == 'POST' else dict(request.args)))
        return func(*args, **kwargs)

    return check


def requests_json(type, url, json_post):
    if type == 'get':
        res = requests.get(url, json.dumps(json_post), headers={'Content-Type': 'application/json'}, timeout=0.5).json()
        return res
    elif type == 'post':
        res = requests.post(url, json.dumps(json_post), headers={'Content-Type': 'application/json'},
                            timeout=0.5).json()
        return res
    return None


def send_logger(func):
    @functools.wraps(func)
    def info(*args, **kwargs):
        current_app.logger.info(
            '{method} {path} : {json}'.format(method=request.method, path=request.environ['PATH_INFO'],
                                              json=request.json))
        return func(*args, **kwargs)

    return info


#
def update_location(name):
    key = 'GjG3XAdmywz7CyETWqHwIuEC6ZExY6QT'
    url = 'http://api.map.baidu.com/geocoder/v2/?output=json&ak=%s&address=' % (key)
    url = url + name
    r = requests.get(url)
    res = r.json()

    if res.get('result', None):
        loc = res['result']['location']
        location = loc['lng'], loc['lat']
        return location
    return None


# 通过最大最小值 获取偏移量
def get_offset(min_id=0, last_id=None, page_size=5):
    offset = 0
    min_id = int(min_id)
    if last_id:
        last_id = int(last_id)
        offset = last_id - page_size
        if offset < 0:
            offset = 0
        return offset
    if min_id > 1:
        offset = min_id - 1
    return offset


# 判断本地和线上的版本号
def compare(local, online):
    l_local = local.split('.')
    l_online = online.split('.')
    f = 0
    flag = False
    if len(l_local) > len(l_online):
        f = len(l_local)
    else:
        f = len(l_online)
    for i in range(f):
        try:
            if l_local[i] < l_online[i]:
                break
            if l_local[i] > l_online[i]:
                flag = True
                break
        except IndexError as e:
            if len(l_local) > len(l_online):
                flag = True
    return flag


def get_date_flag():
    return datetime.now().strftime('%Y-%m')


def get_flag(month_num):
    month_flag = month_num
    if 0 < (month_flag) <= 1:
        return "1"
    elif 1 < (month_flag) <= 2:
        return "2"
    elif 2 < (month_flag) <= 3:
        return "3"
    else:
        return "4"


def get_date_flag_by_datetime(datetime):
    month = datetime.month
    return str(datetime.year) + get_flag(month)


@contextmanager
def try_pass():
    try:
        yield
    except Exception as e:
        print(e)


def check_type(item, type=int):
    try:
        type(item)
    except Exception as e:
        raise ParmesError(message='无效参数类型')
    finally:
        pass


def getEveryDay(begin_date, end_date=None):
    import datetime as _datetime
    date_list = []
    begin_date = datetime.strptime(begin_date, "%Y-%m-%d")
    if end_date is None:
        end_date = datetime.today()
    else:
        end_date = datetime.strptime(end_date, "%Y-%m-%d")
    while begin_date <= end_date:
        date_str = begin_date.strftime("%Y-%m-%d")
        date_list.append(date_str)
        begin_date += _datetime.timedelta(days=1)
    return date_list


def upload_file_to_dfs(file):
    files = [('file', file)]
    data = {'output': 'json', 'path': '', 'scene': ''}
    upload_url = 'http://{}/group1/upload'.format(current_app.config.get('DFS_HOST'))
    try:
        res = requests.post(upload_url, data=data, files=files)
        if res.status_code != 200:
            raise UploadFileError()
        return json.loads(res.text)
    except json.JSONDecodeError as e:
        raise UploadFileError(message='Upload File Failed: Response Decode Error, {}'.format(e))
    except Exception as e:
        raise UploadFileError(message='Upload File Error: {}'.format(e))


def case_list_diff(case_list):
    # diff_list = []
    # for index1, case1 in enumerate(case_list):
    #     for index2, case2 in enumerate(case_list):
    #         if index1 == index2:
    #             continue
    #         result = set(case1).difference(set(case2))
    #         if result:
    #             diff_list.append(result)
    #
    # result = set()
    # for diff in diff_list:
    #     result = result | diff
    # if result:
    #     return True, list(result)
    # return False, []

    result1 = set(case_list[0]).difference(set(case_list[1]))
    result2 = set(case_list[1]).difference(set(case_list[0]))
    if result1 or result2:
        result = result1 | result2
        return True, list(result)
    return False, []


def reckon_time_diff(time1, time2):
    datetime1 = datetime.strptime(list(time1)[0]['datetime'], '%Y-%m-%d %H:%M:%S')
    datetime2 = datetime.strptime(list(time2)[0]['datetime'], '%Y-%m-%d %H:%M:%S')
    rd = dateutil.relativedelta.relativedelta(
        datetime1, datetime2)
    unit_list = ('years', 'months', 'days', 'hours', 'minutes', 'seconds')
    result = ""
    for unit in unit_list:
        current = rd.__getattribute__(unit)
        if current:
            result += f"{current} {unit} "
    if not result:
        result = "1 seconds"
    return result


def reckon_time_diff_v2(time1, time2):
    rd = dateutil.relativedelta.relativedelta(time1, time2)
    unit_list = ('years', 'months', 'days', 'hours')
    result = ""
    for unit in unit_list:
        current = rd.__getattribute__(unit)
        if current:
            result += f"{current} {unit} "
    if not result:
        result = "about 1 minutes"
    return result


def random_code(count=4):
    letters = string.ascii_letters
    Lowercase_letters = string.ascii_lowercase
    Capital = string.ascii_uppercase
    digits = string.digits

    s = Lowercase_letters + digits + Capital
    code = "".join(random.sample(s, count))
    print(f'随机code:{code}')
    return code


def delete_log_file(localfile):
    if (os.path.exists(localfile)):
        os.remove(localfile)


def get_week_display(dt=None):
    if dt and isinstance(dt, datetime):
        return dt.isocalendar()
    else:
        return datetime.now().isocalendar()


def get_3_month_week_col():
    now_year, now_week, _ = get_week_display(datetime.now())
    last_year, last_week, _ = get_week_display(datetime.now() + timedelta(days=90))
    week_col = []
    if now_year == last_year:
        for week in range(now_week, last_week + 1):
            week_col.append(f'{now_year}-{week}')
    else:
        for week in range(now_week, 54):
            week_col.append(f'{now_year}-{week}')
        for week in range(1, last_week):
            week_col.append(f'{last_year}-{week}')
    return week_col


def week_display_sort(week_col):
    week_dict_list = []
    for _week in week_col:
        year, week = _week.split("-")
        week_dict_list.append({"year": year, "week": week, "week_display": _week})

    new_week_dict_list = sorted(week_dict_list, key=lambda x: (int(x["year"]), int(x["week"])))
    new_week_col = [item.get("week_display") for item in new_week_dict_list]
    return new_week_col
